#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#endif

#include <fstream>
#include <string>
#include "simple_c_lexer.h"
#include "gl_header_parser.h"
#include <iostream>

static const unsigned int BUFFERSIZE = 1024 * 1024;
char buffer[BUFFERSIZE];

std::string make_get(std::string url){
	std::string request;
	request += "GET " + url + " HTTP/1.0\r\n";
    request += "Host: www.opengl.org\r\n";
    request += "\r\n";
	return request;
}

std::string get_file(std::string url){
#ifdef _WIN32
	WSADATA wsaData;

	if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
        exit(-1);
#endif
	int sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

	sockaddr_in addr;

	hostent* h = gethostbyname("opengl.org");
	char * ip = inet_ntoa (*(struct in_addr *)*h->h_addr_list);

	memset(&addr, 0, sizeof(addr));
	addr.sin_family      = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip);
    addr.sin_port        = htons(80);

	if(connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0){
		exit(-2);
	}

	std::string req = make_get(url);
	std::string response = "";

	if(send(sock, req.c_str(), req.length(), 0) != req.length()){
		exit(-3);
	}

	int resp_leng = BUFFERSIZE;
	while (resp_leng == BUFFERSIZE){
        resp_leng = recv(sock, (char*)&buffer, BUFFERSIZE, MSG_WAITALL);
        if (resp_leng > 0)
            response += std::string(buffer).substr(0, resp_leng);
    }

	return response.substr(response.find("\r\n\r\n"));
}

void lex(const std::string &f, const std::string &s){
	simple_c_lexer l(s);
	gl_header_parser p(l);
	p.parse();
	std::ofstream o(f.c_str());
	p.dump(o);
}

std::string read_file(const std::string &path){
	std::ifstream l_File(path.c_str());

    if(l_File){
		l_File.seekg(0, std::ios::end);
		std::ifstream::pos_type l_Length = l_File.tellg();
        l_File.seekg(0, std::ios::beg);
		std::vector<char> buffer;
		buffer.resize(l_Length + (std::ifstream::pos_type)1); // to avoid check in read_lexeme
        l_File.read(&buffer[0], l_Length);
		buffer[l_Length] = 0;

		return std::string(buffer.begin(), buffer.end());
	}else{
		throw std::runtime_error("Can't find or read file " + path);
	}
}

int main(int argc, char **argv){
// TODO: do parse comments like this:
/* reuse GL_XXX */
/* Reuse tokens from XX_XXX */ 
/* OpenGL 3.0 also reuses entry points from these extensions: */
/* (no entry points) */

/*
Reuse tokens from 45
reuse GL_ 397
---------------+ = 442

reuses 6

reuse 448
*/
	lex("../glext.h", get_file("/registry/api/glext.h"));
	lex("../glxext.h", get_file("/registry/api/glxext.h"));
	lex("../wglext.h", get_file("/registry/api/wglext.h"));

	return 0;
}